#include <algorithm>

#include "common.h"
#include "simulator.h"
#include "event.h"
#include "eventhandler.h"
#include "timer.h"
#include "config.h"

uint32_t Timer::timer_id_count_ = 0;

Simulator* Simulator::instance_ = NULL;

Simulator::Simulator() 
	: Object()
	, time_(0.0) 
{
	instance_ = this;
}

Simulator::~Simulator()
{
}

bool Simulator::create()
{
	NEW_OBJECT( Simulator, instance_, () ); 
	return true;
}

void Simulator::destroy()
{
	if ( instance_!= NULL ){
		RELEASE_OBJ( instance_ )
	}
}

void Simulator::scheduleEvent( Event *e )
{
	enqueue( e );
}

void Simulator::scheduleEvent( Event *e, sim_time_t delay )
{
	e->setTime( clock() + delay );
	enqueue( e );
}

void Simulator::scheduleTimer( Timer *e, sim_time_t delay )
{
	e->setTime( clock() + delay );
	enqueue( e );
}

bool Simulator::init()
{
	return true;
}

void Simulator::run()
{
	if ( !init() ) return;

	Event *e = dequeue();

	while( (NULL!=e) && isRunning() ){
		time_ = e->getTime();
		if ( Event::TIMER==e->getType() ){
			e->getHandler()->onTimer( static_cast<Timer*>(e) );
		} else{
			e->getHandler()->onEvent( e );
		}
		RELEASE_OBJ(e);
		e = dequeue();
	};

	finalize();
}

bool Simulator::isRunning( void ) const
{
	return ( (config.simulator_.finish_time<0) ||
			(config.simulator_.finish_time>clock()) );
}

void Simulator::finalize()
{
	event_queue_.clearEventQueue();
}

void Simulator::enqueue( Event *e )
{
	e->add_reference();

	event_queue_.insertEvent( e );
}

Event* Simulator::dequeue( void )
{
	return event_queue_.nextEvent();
}
